///////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///////////////////////////////////////////////////////////////////////////////////////////

#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;
namespace {
class Controller {
 public:
  int Num;
  wstring Status;
  vector<weak_ptr<Controller>> others;
  explicit Controller(int i) : Num(i), Status(L"On") {
    wcout << L"Creating Controller" << Num << endl;
  }
  ~Controller() { wcout << L"Destroying Controller" << Num << endl; }
  // Demonstrates how to test whether the
  // pointed-to memory still exists or not.
  void CheckStatuses() const {
    for_each(others.begin(), others.end(), [](weak_ptr<Controller> wp) {
      auto p = wp.lock();
      if (p) {
        wcout << L"Status of " << p->Num << " = " << p->Status << endl;
      } else {
        wcout << L"Null object" << endl;
      }
    });
  }
};

void RunTest() {
  vector<shared_ptr<Controller>> v{
      make_shared<Controller>(0), make_shared<Controller>(1),
      make_shared<Controller>(2), make_shared<Controller>(3),
      make_shared<Controller>(4),
  };

  // Each controller depends on all others not being deleted.
  // Give each controller a pointer to all the others.
  for (int i = 0; i < v.size(); ++i) {
    for_each(v.begin(), v.end(), [&v, i](shared_ptr<Controller> p) {
      if (p->Num != i) {
        v[i]->others.push_back(weak_ptr<Controller>(p));
        wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
      }
    });
  }

  for_each(v.begin(), v.end(), [](shared_ptr<Controller> &p) {
    wcout << L"use_count = " << p.use_count() << endl;
    p->CheckStatuses();
  });
}
}  // namespace

int main() {
  RunTest();
  wcout << L"Press any key" << endl;
  char ch;
  cin.getline(&ch, 1);
}